import xlrd


from Base.BaseSetting import Data_Dir
from Base.KDT import KDT
from xlutils.copy import copy

from Base.PublicFunction import assertException


class PraseExcel():
    def __init__(self,filename):
        self.filename = Data_Dir+filename
        self.book = xlrd.open_workbook(Data_Dir+filename)  #打开一个表格全对象
        self.kdt = KDT() #实例化一个对象kdt

    def ReadExcel(self,tablename):
        self.sheetname = tablename
        self.table = self.book.sheet_by_name(tablename) #打开指定的表格对象
        self.rows = self.table.nrows  #获取表格的全部行
        self.cols = self.table.ncols  #获取表格的全部列
        self.table.get_rows()   #获取指定行的内容

    #获得每行第一列的caseid
    def get_caseid(self,row):
        return self.table.cell_value(row,0) #根据行和列获取单元格的内容

    def get_row_bycaseid(self,caseid,col=0):
        for row in range(self.rows):
            if self.get_caseid(row) == caseid:
                if col:
                    return self.table.cell_value(row,col)
                else:
                    return row

    #获取计划
    def get_caselist_byplan(self,planstr):
        caseidlist = []
        for row in range(self.rows):
            caseid = self.get_caseid(row)
            if self.table.cell_value(row,8) == planstr:
                caseidlist.append(caseid)   #append是基于原列表修改，没有返回值
        return caseidlist  #return必须放在最外层，放在if里面，只要条件满足一次，强制退出


    #获取优先级
    def get_casepriority(self,caseid):
        return self.get_row_bycaseid(caseid,7)

    def get_casemoudle(self,caseid):
        return self.get_row_bycaseid(caseid,5 )

    #获取case前置条件
    def get_casepreconditions(self,caseid):
        return self.get_row_bycaseid(caseid, 3)

    def get_casedesc(self,caseid):
        return self.get_row_bycaseid(caseid, 1)

    #获取case操作步骤
    def get_casestep(self,caseid):
        # 返回二维数组，第一层 操作 步骤 第二层 具体 指令
        casestep_str =  self.get_row_bycaseid(caseid, 2)
        steplist = casestep_str.split('\n')#用换行符/n进行切割成一个列表
        step_detail_list = []
        for step in steplist:
            step_detail = step.split(',')#将每个单元格内的内容再进行切割成一个列表
            step_detail_list.append(step_detail)
        return step_detail_list

    def get_exceptresult(self,caseid):
        return self.get_row_bycaseid(caseid,4 )

    def get_plan(self,caseid):
        return self.get_row_bycaseid(caseid, 8)

    #返回的是一个生成器，返回所有行中的内容
    def get_all_testcase(self):
        return self.table.get_rows_value()

    #方法1：根据caseid 执行指定case步骤
    def do_caseid(self,caseid):
        # print(caseid)
        #直接调用根据caseid生成递归函数merge_case_step(caseid)
        #直接判断有没有前置条件，进行执行，merge_case_step(caseid) 中也有获取步骤列表的操作
        step_detail_list = self.merge_case_step(caseid)
        # print(step_detail_list)
        for step_detail in step_detail_list:
            if step_detail[0].startswith ('assert'):
                resinfo,res = getattr(self.kdt, step_detail[0])(*step_detail[1:])
                row =self.get_row_bycaseid(caseid)
                self.write_data(row,9,resinfo)  #调用写入excel的方法，现在要获取行
                if not res:  #手动加入抛出异常，因为在KDT脚本中断言虽然有误，但是脚本还是通过的，这是不符合常理的，需要将这个异常抛出去捕获到
                    raise assertException(resinfo)  #抛出异常，在try中找到异常并抛出去，在except 中 捕获异常
            else:
                # print(step_detail)
                getattr(self.kdt, step_detail[0])(*step_detail[1:])


    # 方法2：根据caseid 执行指定case步骤，先要执行递归函数
    def do_case_step(self,step_detail_list):
        for step_detail in step_detail_list:
            res = getattr(self.kdt, step_detail[0])(*step_detail[1:])

    #根据caseid  执行全部case步骤
    def do_all_caseid(self):

        for row in range(1, excel.rows):
            caseid = self.get_caseid(row)
            self.do_caseid(caseid)


    #根据caseid生成递归函数，当一个case需要有前置条件时使用
    def merge_case_step(self,caseid):
        pre_cond = self.get_casepreconditions(caseid) #根据caseid获取前置条件，也就是caseid
        step_detail_list = self.get_casestep(caseid) #根据caseid获取对应的操作步骤
        if not pre_cond: #不满足条件时会有返回值
            return step_detail_list
        else:
            step_list = self.merge_case_step(pre_cond) #满足条件时需要再调用一遍merge_case_step()函数
            step_list.extend(step_detail_list) #根据返回值再反推回到最初的caseid，也就是step_list再反推回去
            return step_list

    def write_data(self,row,col,res):  #写入excel表格的方法
        self.book = xlrd.open_workbook(self.filename) #打开旧表格
        new_workbook = copy(self.book) #复制旧的表格
        #获取sheet
        new_worksheet = new_workbook.get_sheet(self.sheetname)

        new_worksheet.write(row,col,res) #依据行和列写入指定的内容

        new_workbook.save(self.filename)

if __name__ == '__main__':
    excel = PraseExcel('易订货系统测试用例1.xlsx')
    excel.ReadExcel('Sheet1')
    excel.do_caseid(9)












